home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / prolog / sbprolog / v3 / modlib_s.lha / modlib_src / $read.P < prev    next >
Text File  |  1990-04-12  |  19KB  |  539 lines

  1. %   File   : READ.PL
  2. %   Author : D.H.D.Warren + Richard O'Keefe
  3. %   Modified for SB-Prolog by Saumya K. Debray & Deeporn Beardsley
  4. %   Updated: July 1988
  5. %   Purpose: Read Prolog terms in Dec-10 syntax.
  6. /*
  7.     Modified by Alan Mycroft to regularise the functor modes.
  8.     This is both easier to understand (there are no more '?'s),
  9.     and also fixes bugs concerning the curious interaction of cut with
  10.     the state of parameter instantiation.
  11.  
  12.     Since this file doesn't provide "metaread", it is considerably
  13.     simplified.  The token list format has been changed somewhat, see
  14.     the comments in the RDTOK file.
  15.  
  16.     I have added the rule X(...) -> apply(X,[...]) for Alan Mycroft.
  17. */
  18.  
  19. $read_export([$read/1,$read/2]).
  20.  
  21. /* $read_use($bmeta,[$atom/1,$atomic/1,$integer/1,$number/1,$structure/1,
  22.         $functor0/2,$bldstr/3,$arg/3,$arity/2,$real/1,$floor/2]).
  23.    $read_use($meta,[$functor/3,$univ/2,$length/2]).
  24.    $read_use($bio,[$writename/1,$writeqname/1,$put/1,$nl/0,$tab/1,
  25.         $tell/1,_,$telling/1,$told/0,$get/1,$get0/1,$see/1,$seeing/1,
  26.         $seen/0]).
  27.    $read_use($io,[$write/1,$writeq/1,$display/1,$print/1]).
  28.    $read_use($blist,[$append/3,$member/2,$memberchk/2]).
  29.    $read_use($retr,[$retract/1,_,_]).
  30.    $read_use($name,[$name/2,$name0/2]).
  31. */
  32.  
  33. %   $read(?Answer).
  34.  
  35. $read(Answer) :- $read(Answer,_).
  36.  
  37. %   $read(?Answer, ?Variables)
  38. %   reads a term from the current input stream and unifies it with
  39. %   Answer.  Variables is bound to a list of [Atom=Variable] pairs.
  40.  
  41. $read(Answer, Variables) :-
  42.         repeat,
  43.             $read_tokens(Tokens, Variables),
  44.             (   $read(Tokens, 1200, Term, LeftOver), $read_all(LeftOver) ;
  45.                 $read_syntax_error(Tokens)
  46.             ),
  47.         !,
  48.         Answer = Term.
  49.  
  50.  
  51. %   $read_all(+Tokens)
  52. %   checks that there are no unparsed tokens left over.
  53.  
  54. $read_all([]) :- !.
  55. $read_all(S) :-
  56.         $read_syntax_error(['operator expected after expression'], S).
  57.  
  58.  
  59. %   $read_expect(Token, TokensIn, TokensOut)
  60. %   reads the next token, checking that it is the one expected, and
  61. %   giving an error message if it is not.  It is used to look for
  62. %   right brackets of various sorts, as they're all we can be sure of.
  63.  
  64. $read_expect(Token, [Token|Rest], Rest) :- !.
  65. $read_expect(Token, S0, _) :-
  66.         $read_syntax_error([Token,'or operator expected'], S0).
  67.  
  68.  
  69. %   I want to experiment with having the operator information held as
  70. %   ordinary Prolog facts.  For the moment the following predicates
  71. %   remain as interfaces to curr_op.
  72. %   $read_prefixop(O -> Self, Rarg)
  73. %   $read_postfixop(O -> Larg, Self)
  74. %   $read_infixop(O -> Larg, Self, Rarg)
  75.  
  76.  
  77. $read_prefixop(Op, Prec, Prec) :-
  78.         $read_curr_op(Prec, fy, Op), !.
  79. $read_prefixop(Op, Prec, Less) :-
  80.         $read_curr_op(Prec, fx, Op), !,
  81.         Less is Prec-1.
  82.  
  83.  
  84. $read_postfixop(Op, Prec, Prec) :-
  85.         $read_curr_op(Prec, yf, Op), !.
  86. $read_postfixop(Op, Less, Prec) :-
  87.         $read_curr_op(Prec, xf, Op), !, Less is Prec-1.
  88.  
  89.  
  90. $read_infixop(Op, Less, Prec, Less) :-
  91.         $read_curr_op(Prec, xfx, Op), !, Less is Prec-1.
  92. $read_infixop(Op, Less, Prec, Prec) :-
  93.         $read_curr_op(Prec, xfy, Op), !, Less is Prec-1.
  94. $read_infixop(Op, Prec, Prec, Less) :-
  95.         $read_curr_op(Prec, yfx, Op), !, Less is Prec-1.
  96.  
  97.  
  98. $read_ambigop(F, L1, O1, R1, L2, O2) :-
  99.         $read_postfixop(F, L2, O2),
  100.         $read_infixop(F, L1, O1, R1), !.
  101.  
  102.  
  103. %   $read(+TokenList, +Precedence, -Term, -LeftOver)
  104. %   parses a Token List in a context of given Precedence,
  105. %   returning a Term and the unread Left Over tokens.
  106.  
  107. :- mode($read,4,[nv,nv,d,d]).
  108.  
  109. $read([Token|RestTokens], Precedence, Term, LeftOver) :-
  110.         $read(Token, RestTokens, Precedence, Term, LeftOver).
  111. $read([], _, _, _) :-
  112.         $read_syntax_error(['expression expected'], []).
  113.  
  114.  
  115. %   $read(+Token, +RestTokens, +Precedence, -Term, -LeftOver)
  116.  
  117. :- mode($read,5,[nv,nv,c,d,d]).
  118.  
  119. $read(var(Variable,_), ['('|S1], Precedence, Answer, S) :- !,
  120.         $read(S1, 999, Arg1, S2),
  121.         $read_args(S2, RestArgs, S3), !,
  122.         $read_exprtl0(S3,apply(Variable,[Arg1|RestArgs]),Precedence,Answer,S).
  123.  
  124. $read(var(Variable,_), S0, Precedence, Answer, S) :- !,
  125.         $read_exprtl0(S0, Variable, Precedence, Answer, S).
  126.  
  127. $read(atom(-), [number(Num)|S1], Precedence, Answer, S) :-
  128.         Negative is -Num, !,
  129.         $read_exprtl0(S1, Negative, Precedence, Answer, S).
  130.  
  131. $read(atom(Functor), ['('|S1], Precedence, Answer, S) :- !,
  132.         $read(S1, 999, Arg1, S2),
  133.         $read_args(S2, RestArgs, S3),
  134.         $univ(Term,[Functor,Arg1|RestArgs]), !,
  135.         $read_exprtl0(S3, Term, Precedence, Answer, S).
  136.  
  137. $read(atom(Functor), S0, Precedence, Answer, S) :-
  138.         $read_prefixop(Functor, Prec, Right), !,
  139.         $read_aft_pref_op(Functor, Prec, Right, S0, Precedence, Answer, S).
  140.  
  141. $read(atom(Atom), S0, Precedence, Answer, S) :- !,
  142.         $read_exprtl0(S0, Atom, Precedence, Answer, S).
  143.  
  144. $read(number(Num), S0, Precedence, Answer, S) :- !,
  145.         $read_exprtl0(S0, Num, Precedence, Answer, S).
  146.  
  147. $read('[', [']'|S1], Precedence, Answer, S) :- !,
  148.         $read_exprtl0(S1, [], Precedence, Answer, S).
  149.  
  150. $read('[', S1, Precedence, Answer, S) :- !,
  151.         $read(S1, 999, Arg1, S2),
  152.         $read_list(S2, RestArgs, S3), !,
  153.         $read_exprtl0(S3, [Arg1|RestArgs], Precedence, Answer, S).
  154.  
  155. $read('(', S1, Precedence, Answer, S) :- !,
  156.         $read(S1, 1200, Term, S2),
  157.         $read_expect(')', S2, S3), !,
  158.         $read_exprtl0(S3, Term, Precedence, Answer, S).
  159.  
  160. $read(' (', S1, Precedence, Answer, S) :- !,
  161.         $read(S1, 1200, Term, S2),
  162.         $read_expect(')', S2, S3), !,
  163.         $read_exprtl0(S3, Term, Precedence, Answer, S).
  164.  
  165. $read('{', ['}'|S1], Precedence, Answer, S) :- !,
  166.         $read_exprtl0(S1, '{}', Precedence, Answer, S).
  167.  
  168. $read('{', S1, Precedence, Answer, S) :- !,
  169.         $read(S1, 1200, Term, S2),
  170.         $read_expect('}', S2, S3), !,
  171.         $read_exprtl0(S3, '{}'(Term), Precedence, Answer, S).
  172.  
  173. $read(string(List), S0, Precedence, Answer, S) :- !,
  174.         $read_exprtl0(S0, List, Precedence, Answer, S).
  175.  
  176. $read(Token, S0, _, _, _) :-
  177.         $read_syntax_error([Token,'cannot start an expression'], S0).
  178.  
  179.  
  180. %   $read_args(+Tokens, -TermList, -LeftOver)
  181. %   parses {',' expr(999)} ')' and returns a list of terms.
  182.  
  183. $read_args([Tok|S1], Term, S) :-
  184.         '_$savecp'(CP),
  185.         $read_args1(Tok,Term,S,S1,CP), '_$cutto'(CP).
  186. $read_args(S, _, _) :-
  187.         $read_syntax_error([', or ) expected in arguments'], S).
  188.  
  189. :- mode($read_args1,5,[c,nv,d,d,d]).
  190.  
  191. $read_args1(',',[Term|Rest],S,S1,CP) :- 
  192.         $read(S1, 999, Term, S2), '_$cutto'(CP),
  193.         $read_args(S2, Rest, S).
  194. $read_args1(')',[],S,S,_).
  195.  
  196.  
  197.  
  198. %   $read_list(+Tokens, -TermList, -LeftOver)
  199. %   parses {',' expr(999)} ['|' expr(999)] ']' and returns a list of terms.
  200.  
  201. $read_list([Tok|S1],Term,S) :-
  202.         '_$savecp'(CP),
  203.         $read_list1(Tok,Term,S,S1,CP),
  204.         '_$cutto'(CP).
  205. $read_list(S, _, _) :-
  206.         $read_syntax_error([', | or ] expected in list'], S).
  207.  
  208.  
  209. :- mode($read_list1,5,[c,nv,d,d,d]).
  210.  
  211. $read_list1(',',[Term|Rest],S,S1,CP) :-
  212.         $read(S1, 999, Term, S2), '_$cutto'(CP),
  213.         $read_list(S2, Rest, S).
  214. $read_list1('|',Rest,S,S1,CP) :-
  215.         $read(S1, 999, Rest, S2), '_$cutto'(CP),
  216.         $read_expect(']', S2, S).
  217. $read_list1(']',[],S,S,_).
  218.  
  219.  
  220. %   $read_aft_pref_op(+Op, +Prec, +ArgPrec, +Rest, +Precedence, -Ans, -LeftOver)
  221.  
  222. :- mode($read_aft_pref_op,7,[nv,nv,nv,nv,nv,d,d]).
  223.  
  224. $read_aft_pref_op(Op, Oprec, Aprec, S0, Precedence, _, _) :-
  225.         Precedence < Oprec, !,
  226.         $read_syntax_error(['prefix operator',Op,'in context with precedence '
  227.                         ,Precedence], S0).
  228.  
  229. $read_aft_pref_op(Op, Oprec, Aprec, S0, Precedence, Answer, S) :-
  230.         $read_peepop(S0, S1),
  231.         $read_prefix_is_atom(S1, Oprec), % can't cut but would like to
  232.         $read_exprtl(S1, Oprec, Op, Precedence, Answer, S).
  233.  
  234. $read_aft_pref_op(Op, Oprec, Aprec, S1, Precedence, Answer, S) :-
  235.         $read(S1, Aprec, Arg, S2),
  236.         $univ(Term,[Op,Arg]), !,
  237.         $read_exprtl(S2, Oprec, Term, Precedence, Answer, S).
  238.  
  239.  
  240. %   The next clause fixes a bug concerning "mop dop(1,2)" where
  241. %   mop is monadic and dop dyadic with higher Prolog priority.
  242.  
  243. $read_peepop([atom(F),'('|S1], [atom(F),'('|S1]) :- !.
  244. $read_peepop([atom(F)|S1], [infixop(F,L,P,R)|S1]) :- 
  245.         $read_infixop(F, L, P, R).
  246. $read_peepop([atom(F)|S1], [postfixop(F,L,P)|S1]) :- 
  247.         $read_postfixop(F, L, P).
  248. $read_peepop(S0, S0).
  249.  
  250.  
  251. %   $read_prefix_is_atom(+TokenList, +Precedence)
  252. %   is true when the right context TokenList of a prefix operator
  253. %   of result precedence Precedence forces it to be treated as an
  254. %   atom, e.g. (- = X), p(-), [+], and so on.
  255.  
  256. $read_prefix_is_atom([Token|_], Precedence) :-
  257.         $read_prefix_is_atom(Token, Precedence).
  258.  
  259. $read_prefix_is_atom(infixop(_,L,_,_), P) :- L >= P.
  260. $read_prefix_is_atom(postfixop(_,L,_), P) :- L >= P.
  261. $read_prefix_is_atom(')', _).
  262. $read_prefix_is_atom(']', _).
  263. $read_prefix_is_atom('}', _).
  264. $read_prefix_is_atom('|', P) :- 1100 >= P.
  265. $read_prefix_is_atom(',', P) :- 1000 >= P.
  266. $read_prefix_is_atom([],  _).
  267.  
  268.  
  269. %   $read_exprtl0(+Tokens, +Term, +Prec, -Answer, -LeftOver)
  270. %   is called by read/4 after it has read a primary (the Term).
  271. %   It checks for following postfix or infix operators.
  272.  
  273. $read_exprtl0([atom(F)|S1], Term, Precedence, Answer, S) :-
  274.     $read_ambigop(F, L1, O1, R1, L2, O2), !,
  275.     (   $read_exprtl([infixop(F,L1,O1,R1)|S1],0,Term,Precedence,Answer,S)
  276.     ;   $read_exprtl([postfixop(F,L2,O2) |S1],0,Term,Precedence,Answer,S)
  277.     ).
  278. $read_exprtl0([atom(F)|S1], Term, Precedence, Answer, S) :-
  279.     $read_infixop(F, L1, O1, R1), !,
  280.     $read_exprtl([infixop(F,L1,O1,R1)|S1],0,Term,Precedence,Answer,S).
  281. $read_exprtl0([atom(F)|S1], Term, Precedence, Answer, S) :-
  282.     $read_postfixop(F, L2, O2), !,
  283.     $read_exprtl([postfixop(F,L2,O2)|S1], 0, Term, Precedence, Answer, S).
  284. $read_exprtl0([','|S1], Term, Precedence, Answer, S) :-
  285.     Precedence >= 1000, !,
  286.     $read(S1, 1000, Next, S2), !,
  287.     $read_exprtl(S2, 1000, (Term,Next), Precedence, Answer, S).
  288. $read_exprtl0(['|'|S1], Term, Precedence, Answer, S) :-
  289.     Precedence >= 1100, !,
  290.     $read(S1, 1100, Next, S2), !,
  291.     $read_exprtl(S2, 1100, (Term;Next), Precedence, Answer, S).
  292. $read_exprtl0([Thing|S1], _, _, _, _) :-
  293.     $read_cfexpr(Thing, Culprit), !,
  294.     $read_syntax_error([Culprit,follows,expression], [Thing|S1]).
  295. $read_exprtl0(S, Term, _, Term, S).
  296.  
  297. :- mode($read_cfexpr,2,[nv,d]).
  298.  
  299. $read_cfexpr(atom(_),       atom).
  300. $read_cfexpr(var(_,_),      variable).
  301. $read_cfexpr(number(_),     number).
  302. $read_cfexpr(string(_),     string).
  303. $read_cfexpr(' (',          bracket).
  304. $read_cfexpr('(',           bracket).
  305. $read_cfexpr('[',           bracket).
  306. $read_cfexpr('{',           bracket).
  307.  
  308.  
  309. :- mode($read_exprtl,6,[nv,d,d,c,d,d]).
  310.  
  311. $read_exprtl([infixop(F,L,O,R)|S1], C, Term, Precedence, Answer, S) :-
  312.     Precedence >= O, C =< L, !,
  313.     $read(S1, R, Other, S2),
  314.     Expr =.. [F,Term,Other], /*!,*/
  315.     $read_exprtl(S2, O, Expr, Precedence, Answer, S).
  316. $read_exprtl([postfixop(F,L,O)|S1], C, Term, Precedence, Answer, S) :-
  317.     Precedence >= O, C =< L, !,
  318.     Expr =.. [F,Term],
  319.     $read_peepop(S1, S2),
  320.     $read_exprtl(S2, O, Expr, Precedence, Answer, S).
  321. $read_exprtl([','|S1], C, Term, Precedence, Answer, S) :-
  322.     Precedence >= 1000, C < 1000, !,
  323.     $read(S1, 1000, Next, S2), /*!,*/
  324.     $read_exprtl(S2, 1000, (Term,Next), Precedence, Answer, S).
  325. $read_exprtl(['|'|S1], C, Term, Precedence, Answer, S) :-
  326.     Precedence >= 1100, C < 1100, !,
  327.     $read(S1, 1100, Next, S2), /*!,*/
  328.     $read_exprtl(S2, 1100, (Term;Next), Precedence, Answer, S).
  329. $read_exprtl(S, _, Term, _, Term, S).
  330.  
  331.  
  332. %   This business of syntax errors is tricky.  When an error is detected,
  333. %   we have to write out a message.  We also have to note how far it was
  334. %   to the end of the input, and for this we are obliged to use the data-
  335. %   base.  Then we fail all the way back to $read(), and that prints the
  336. %   input list with a marker where the error was noticed.  If subgoal_of
  337. %   were available in compiled code we could use that to find the input
  338. %   list without hacking the data base.  The really hairy thing is that
  339. %   the original code noted a possible error and backtracked on, so that
  340. %   what looked at first sight like an error sometimes turned out to be
  341. %   a wrong decision by the parser.  This version of the parser makes
  342. %   fewer wrong decisions, and $ goal was to get it to do no backtracking
  343. %   at all.  This goal has not yet been met, and it will still occasionally
  344. %   report an error message and then decide that it is happy with the input
  345. %   after all.  Sorry about that.
  346.  
  347. /*  Modified by Sau$a Debray, Nov 18 1986, to use SB-Prolog's database
  348.     facilities to print out error messages.                             */
  349.  
  350. $read_syntax_error(Message, List) :-
  351. /*      $print('**'), $print_list(Message), $nl, */
  352.  
  353.         $length(List,Length),
  354.         $symtype('_$synerr'(_),X),
  355.         ( (X =:= 0 ; not('_$synerr'(_))) ->     /* _$synerr/1 undefined */
  356.                 $assert('_$synerr'(Length)) ;
  357.                 true
  358.         ),
  359.         !,
  360.         fail.
  361.  
  362. $read_syntax_error(List) :-
  363.         $nl, $print('*** syntax error ***'), $nl,
  364.         '_$synerr'(AfterError),
  365.         $retract('_$synerr'(AfterError)),
  366.         $length(List,Length),
  367.         BeforeError is Length - AfterError,
  368.         $read_display_list(List,BeforeError), !,
  369.         fail.
  370.  
  371. $read_display_list(X, 0) :-
  372.         $print('<<here>> '), !,
  373.         $read_display_list(X, 99999).
  374. $read_display_list([Head|Tail], BeforeError) :-
  375.         $print_token(Head),
  376.         $writename(' '),
  377.         Left is BeforeError-1, !,
  378.         $read_display_list(Tail, Left).
  379. $read_display_list([], _) :-
  380.         $nl.
  381.  
  382.  
  383. $print_list([]) :- $nl.
  384. $print_list([Head|Tail]) :-
  385.         $tab(1),
  386.         $print_token(Head),
  387.         $print_list(Tail).
  388.  
  389. $print_token(atom(X))    :- !, $print(X).
  390. $print_token(var(V,X))   :- !, $print(X).
  391. $print_token(number(X)) :-  !, $print(X).
  392. $print_token(string(X))  :- !, $print(X).
  393. $print_token(X)          :-    $print(X).
  394.  
  395.  
  396. /*
  397. %   $read_tokens(TokenList, Dictionary)
  398. %   returns a list of tokens.  It is needed to "prime" read_tokens/2
  399. %   with the initial blank, and to check for end of file.  The
  400. %   Dictionary is a list of AtomName=Variable pairs in no particular order.
  401. %   The way end of file is handled is that everything else FAILS when it
  402. %   hits character "-1", sometimes printing a warning.  It might have been
  403. %   an idea to return the atom 'end_of_file' instead of the same token list
  404. %   that you'd have got from reading "end_of_file. ", but (1) this file is
  405. %   for compatibility, and (b) there are good practical reasons for wanting
  406. %   this behaviour. */
  407.  
  408. $read_tokens(TokenList, Dictionary) :-
  409.         $read_next_token(Type,Value),
  410.     $read_insert_token(Type,Value,Dict,ListOfTokens),
  411.         $append(Dict, [], Dict), !, /*  fill in the "hole" at the end */
  412.         Dictionary = Dict,              /*  unify explicitly so we read and */
  413.         TokenList = ListOfTokens.       /*  then check even with filled in */
  414.                                         /*  arguments */
  415. $read_tokens([atom(end_of_file)], []).   /*  only thing that can go wrong */
  416.  
  417. $read_next_token(Type, Value) :- '_$builtin'(135).
  418.  
  419.  
  420. /*
  421. $read_insert_token(0,Val,Dict,Tokens):-         % number 
  422.     Tokens = [number(Val) | TokRest],
  423.         $read_next_token(Type,Value),
  424.     $read_insert_token(Type,Value,Dict,TokRest).
  425.  
  426. $read_insert_token(1,Val,Dict,Tokens):-       % atom 
  427.     Tokens = [atom(Val) | TokRest]
  428.         $read_next_token(Type,Value),
  429.     $read_insert_token(Type,Value,Dict,TokRest).
  430.  
  431. $read_insert_token(2,Val,Dict,Tokens):-        % atom( 
  432.     Tokens = [atom(Val) | ['(' | TokRest]],
  433.         $read_next_token(Type,Value),
  434.     $read_insert_token(Type,Value,Dict,TokRest).
  435.  
  436. $read_insert_token(3,Name,Dict,Tokens):-       % var 
  437.     Tokens = [var(Var,Name) | TokRest],
  438.     $read_lookup(Dict, Name=Var),
  439.         $read_next_token(Type,Value),
  440.     $read_insert_token(Type,Value,Dict,TokRest).
  441.  
  442. $read_insert_token(4,Val,Dict,Tokens):-        % uscore 
  443.     Tokens = [var(_,Val) | TokRest],
  444.         $read_next_token(Type,Value),
  445.     $read_insert_token(Type,Value,Dict,TokRest).
  446.  
  447. $read_insert_token(5,Val,Dict,Tokens):-        % string 
  448.     Tokens = [string(Val) | TokRest],
  449.         $read_next_token(Type,Value),
  450.     $read_insert_token(Type,Value,Dict,TokRest).
  451.  
  452. $read_insert_token(6,Val,Dict,Tokens):-        % punctuation 
  453.     Tokens = [Val | TokRest], 
  454.         $read_next_token(Type,Value),
  455.     $read_insert_token(Type,Value,Dict,TokRest).
  456.  
  457. $read_insert_token(7,_,Dict,Tokens):-        % semicolon 
  458.     Tokens = [atom((';')) | TokRest],
  459.         $read_next_token(Type,Value),
  460.     $read_insert_token(Type,Value,Dict,TokRest).
  461.  
  462. $read_insert_token(8,_,_,[]).    % end of clause 
  463.  
  464. */
  465.  
  466. $read_insert_token(X,Val,Dict,Tokens):-            
  467.   (X=:=0 ->
  468.       /**0**/                           /* punctuation */
  469.       (Tokens = [Val | TokRest],
  470.        $read_next_token(Type,Value),
  471.        $read_insert_token(Type,Value,Dict,TokRest)
  472.       );
  473.       (X<3 ->
  474.      (X=:=1 ->                      /* var */
  475.         /**1**/
  476.         (Val = Name, Tokens = [var(Var,Name) | TokRest], 
  477.          $read_lookup(Dict, Name=Var),
  478.          $read_next_token(Type,Value), 
  479.          $read_insert_token(Type,Value,Dict,TokRest)
  480.         );
  481.         /**2**/                    /* atom( */
  482.         (Tokens = [atom(Val) | ['(' | TokRest]],
  483.              $read_next_token(Type,Value),
  484.          $read_insert_token(Type,Value,Dict,TokRest)
  485.         )
  486.      );
  487.      (X<5 ->
  488.         (X=:=3 ->
  489.            /**3**/                /* number */
  490.            (Tokens = [number(Val) | TokRest],
  491.             $read_next_token(Type,Value),
  492.             $read_insert_token(Type,Value,Dict,TokRest)
  493.            ) ;
  494.            /**4**/                /* atom */
  495.            (Tokens = [atom(Val) | TokRest],
  496.             $read_next_token(Type,Value),
  497.          $read_insert_token(Type,Value,Dict,TokRest)
  498.            )
  499.         );
  500.         (X<7 ->
  501.            (X=:=5 ->
  502.            /**5**/                /* end of clause */
  503.            Tokens = [] ;
  504.            /**6**/            /* uscore */
  505.            (Tokens = [var(_,Val) | TokRest],
  506.             $read_next_token(Type,Value),
  507.                 $read_insert_token(Type,Value,Dict,TokRest)
  508.            )
  509.            ) ;
  510.            (X=:=7 ->
  511.            /**7**/            /* semicolon */
  512.            (Tokens = [atom((';')) | TokRest],
  513.             $read_next_token(Type,Value),
  514.                 $read_insert_token(Type,Value,Dict,TokRest)
  515.            );
  516.                  (X=:=8 ->
  517.                /**8**/            /* end of file */
  518.                fail ;
  519.                /**9**/            /* string */
  520.                (Tokens = [string(Val) | TokRest],
  521.                 $read_next_token(Type,Value),
  522.             $read_insert_token(Type,Value,Dict,TokRest)
  523.                )
  524.            )
  525.            )
  526.         )
  527.          )
  528.       )
  529.   ).
  530.  
  531.  
  532. /* 
  533. %   read_lookup is identical to memberchk except for argument order and
  534. %   mode declaration.
  535. */
  536.  
  537. $read_lookup([X|_], X) :- !.
  538. $read_lookup([_|T], X) :- $read_lookup(T, X).
  539.